
# ifndef __DFX_GRAPHICS_DEVICE_OGL_H__
# define __DFX_GRAPHICS_DEVICE_OGL_H__

# include "dfxGraphicsDevice.h"
# include "dfxRenderState_OGL.h"
# include "dfxProgram_OGL.h"
# include "dfxTexture_OGL.h"
# include "dfxRenderData_OGL.h"
# include "dfxMaterial.h"

# include <GL/glew.h>
# include <GL/GL.h>

namespace DFX
{
    class GraphicsDevice_OGL : public GraphicsDevice, WindowCallback
    {
    private:

        Window              *mWindow;        
        bool                mInitialized;
                
        AlphaState_OGL      *mOldAlphaState;
        RasterizerState_OGL *mOldRasterizerState;
        DepthState_OGL      *mOldDepthState;
        StencilState_OGL    *mOldStencilState;

        RenderData          *mOldRenderData;
        Program             *mOldProgram;
        Texture             **mOldTextures;

    public:

        GraphicsDevice_OGL();
        ~GraphicsDevice_OGL();

        bool IsInitialized() const
        {
            return mInitialized;
        }

        Window* GetWindow();

        DFXRESULT Initialize(Window *window);
        DFXRESULT Destroy();

        DFXRESULT CreateAdditional(Window *window);

        Texture* CreateTexture(const String &name, TEXTURE_TYPE type, UInt32 usage, bool mipMaps);
        Program* CreateProgram(const String &name);
        RenderData* CreateRenderData(const String &name);

        AlphaState* CreateAlphaState(const AlphaStateDescription &desc);
        RasterizerState* CreateRasterizeState(const RasterizerStateDescription &desc);
        DepthState* CreateDepthState(const DepthStateDescription &desc);
        StencilState* CreateStencilState(const StencilStateDescription &desc);

        void SetAlphaState(AlphaState *state);
        void SetRasterizerState(RasterizerState *state);
        void SetDepthState(DepthState *state);
        void SetStencilState(StencilState *state);
        void SetMaterial(Material *mat);
        void SetRenderData(RenderData *data);

        void Clear(UInt32 flags, const Color4 &c, Float32 depth, Int32 stencil);

        void Present(Window *window);
        void SetCurrent(Window *window);

        void OnCreate(Window *w);
        void OnDestroy(Window *w);

        void OnActivate(Window *w);
        void OnDeactivate(Window *w);

        void OnResize(Window *w, UInt32 width, UInt32 height);

    private:

        void InitializeDefaults();

    public:

        static GLenum  TextureType[TEXTURE_TYPE_MAX];
        static GLenum  TextureWrap[TEXTURE_WRAP_MAX];
        static GLenum  SurfaceFormat[SURFACE_FORMAT_MAX];
        static GLenum  ImageFormat[IMAGE_FORMAT_MAX];
        static GLenum  ShaderType[SHADER_TYPE_MAX];
        static GLenum  VertexElementFormat[VERTEX_ELEMENT_FORMAT_MAX];
        static GLenum  BufferUsage[BUFFER_USAGE_MAX];
        static GLenum  PrimitiveType[PRIMITIVE_TYPE_MAX];
        static GLenum  BlendOption[BLEND_OPTION_COUNT];
        static GLenum  BlendEquation[BLEND_EQUATION_COUNT];
        static GLenum  CompareFunction[COMPARE_FUNCTION_COUNT];
        static GLenum  StencilOption[STENCIL_OPTION_COUNT];
        static GLenum  StencilFace[STENCIL_FACE_COUNT];
        static GLenum  PolygonMode[FILL_MODE_COUNT];
    };
}

# endif